package com.jmz.apt.api.Utils;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by fanglexue on 2019/10/28.
 */
public class ObjectUtil {

    /**
     * 返回的object转需要的对象
     *
     * @param o         需要转换的对象
     * @param valueType 類型
     * @param <T>       返回值定义一个泛型T
     * @return t 需要的对象
     */
    public static <T> T toObj(Object o, Class<T> valueType) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            String json = mapper.writeValueAsString(o);
            T t = mapper.readValue(json, valueType);
            return t;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 对象转json
     *
     * @param o 对象
     * @return json字符串
     */
    public static String obj2json(Object o) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            String json = mapper.writeValueAsString(o);
            return json;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * json转对象
     *
     * @param json
     * @param valueType 对象类型
     * @param <T>       返回值定义一个泛型T
     * @return 需要的对象
     */
    public static <T> T json2obj(String json, Class<T> valueType) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            //忽略反序列化解析异常
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
            T t = mapper.readValue(json, valueType);
            return t;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 将json转换成对象TypeReference
     *
     * @param json
     * @param typeReference
     * @param <T>
     * @return
     */
    public static <T> T json2obj(String json, TypeReference<T> typeReference) {
        if (StringUtils.isEmpty(json) || typeReference == null) {
            return null;
        }
        ObjectMapper mapper = new ObjectMapper();
        try {
            return (T) (typeReference.getType().equals(String.class) ? json : mapper.readValue(json, typeReference));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将json转换成对象
     *
     * @param json
     * @param collectionClass
     * @param elementClasses
     * @param <T>
     * @return
     */
    public static <T> T json2obj(String json, Class<?> collectionClass, Class<?>... elementClasses) {
        ObjectMapper mapper = new ObjectMapper();
        JavaType javaType = mapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
        try {
            return mapper.readValue(json, javaType);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 实体对象转成Map
     *
     * @param obj 实体对象
     * @return
     */
    public static Map<String, Object> object2Map(Object obj) {
        Map<String, Object> map = new HashMap<>();
        if (obj == null) {
            return map;
        }
        Class clazz = obj.getClass();
        Field[] fields = clazz.getDeclaredFields();
        try {
            for (Field field : fields) {
                field.setAccessible(true);
                map.put(field.getName(), field.get(obj));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * Map转成实体对象
     *
     * @param map   map实体对象包含属性
     * @param clazz 实体对象类型
     * @return
     */
    public static <T> T map2Object(Map<String, Object> map, Class<T> clazz) {
        if (map == null) {
            return null;
        }
        T obj = null;
        try {
            obj = clazz.newInstance();
            Field[] fields = obj.getClass().getDeclaredFields();
            for (Field field : fields) {
                int mod = field.getModifiers();
                if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
                    continue;
                }
                field.setAccessible(true);
                if (map.get(field.getName())!=null){
                    String data = map.get(field.getName()).toString().trim();
                    if (field.getGenericType() == Date.class) {
                        SimpleDateFormat sdf = null;
                        if (data.length() == 10) {
                            sdf = new SimpleDateFormat("yyyy-MM-dd");
                        } else {
                            sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        }
                        field.set(obj, sdf.parse(data));
                    } else if (field.getGenericType() == Double.class) {
                        field.set(obj, Double.parseDouble(data));
                    } else if (field.getGenericType() == Integer.class) {
                        field.set(obj, Integer.parseInt(data));
                    } else if (field.getGenericType() == Long.class) {
                        field.set(obj, Long.parseLong(data));
                    } else {
                        field.set(obj, data);
                    }
                }else {
                    field.set(obj, map.get(field.getName()));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return obj;
    }

    /**
     * 将 List<Map>对象转化为List<JavaBean>
     *
     * @param listMap
     * @param valueType
     * @return Object对象
     */
    public static <T> List<T> convertListMap2ListBean(List listMap, Class<T> valueType) {
        List<T> beanList = new ArrayList<T>();
        for (int i = 0, n = listMap.size(); i < n; i++) {
            Map<String, Object> map = (Map<String, Object>) listMap.get(i);
            T bean = map2Object(map, valueType);
            beanList.add(bean);
        }
        return beanList;
    }

    /**
     * 堆内存对象克隆
     *
     * @param o 实体对象类型
     * @return
     */
    public static <T> T clone(T o) {
        T obj = null;
        try {
            obj = (T)o.getClass().newInstance();
            Field[] fields = obj.getClass().getDeclaredFields();
            for (Field field : fields) {
                int mod = field.getModifiers();
                if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
                    continue;
                }
                field.setAccessible(true);
                field.set(obj,field.get(o));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return obj;
    }
}

